package moe.codeest.enviews;

import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.Path;
import ohos.agp.render.PathMeasure;
import ohos.agp.utils.Color;
import ohos.agp.utils.Point;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;

/**
 * Created by codeest on 16/11/9.
 * <p>
 * 我把它做成了SwitchView...不知道设计师是不是这个想法..  0.0
 */

public class ENScrollView extends Component implements Component.DrawTask, Component.LayoutRefreshedListener {

    private static final int STATE_SELECT = 0;

    private static final int STATE_UNSELECT = 1;

    private static final int DEFAULT_LINE_COLOR = 0xffffffff;

    private static final int DEFAULT_BG_LINE_COLOR = 0xff444a4f;

    private static final int DEFAULT_LINE_WIDTH = 10;

    private static final int DEFAULT_BG_LINE_WIDTH = 10;

    private static final int DEFAULT_DURATION = 700;

    private static final int DEFAULT_VIEW_TRANSLATION_X = 16;

    private static final boolean DEFAULT_STATE = false;

    private int mCurrentState = STATE_UNSELECT;

    private int mCurrentColor = DEFAULT_LINE_COLOR;

    private Paint mPaint, mBgPaint, mColorPaint;

    private Path mPath, mDstPath;

    private PathMeasure mPathMeasure;

    private RectFloat mRectF;

    private float mFraction;

    private float mWidth, mHeight;

    private float mCenterX, mCenterY;

    private float mCircleRadius;

    private float mPathLength;

    private boolean isInit = false;

    private int mLineColor, mBgLineColor, mDuration, mViewTranslationX;

    public ENScrollView(Context context) {
        this(context, null);
    }

    public ENScrollView(Context context, AttrSet attrSet) {
        this(context, attrSet, null);
    }

    public ENScrollView(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        int lineColor = AttrUtils.getColorFromAttr(attrSet, "scroll_line_color", DEFAULT_LINE_COLOR);
        int lineWidth = AttrUtils.getDimensionFromAttr(attrSet, "scroll_line_width", DEFAULT_LINE_WIDTH);
        int bgLineColor = AttrUtils.getColorFromAttr(attrSet, "scroll_bg_line_color", DEFAULT_BG_LINE_COLOR);
        int bgLineWidth = AttrUtils.getDimensionFromAttr(attrSet, "scroll_bg_line_width", DEFAULT_BG_LINE_WIDTH);
        boolean isSelected = AttrUtils.getBooleanFromAttr(attrSet, "scroll_is_selected", DEFAULT_STATE);
        int viewTranslationX = AttrUtils.getDimensionFromAttr(attrSet, "scroll_view_translation_x", DEFAULT_VIEW_TRANSLATION_X);

        mLineColor = lineColor;
        mBgLineColor = bgLineColor;

        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.STROKE_STYLE);
        mPaint.setStrokeCap(Paint.StrokeCap.ROUND_CAP);
        mPaint.setColor(new Color(lineColor));
        mPaint.setStrokeWidth(lineWidth);

        mBgPaint = new Paint();
        mBgPaint.setAntiAlias(true);
        mBgPaint.setStyle(Paint.Style.STROKE_STYLE);
        mBgPaint.setStrokeCap(Paint.StrokeCap.ROUND_CAP);
        mBgPaint.setColor(new Color(bgLineColor));
        mBgPaint.setStrokeWidth(bgLineWidth);

        mColorPaint = new Paint();
        mColorPaint.setAntiAlias(true);
        mColorPaint.setStyle(Paint.Style.FILL_STYLE);
        mColorPaint.setStrokeCap(Paint.StrokeCap.ROUND_CAP);
        mColorPaint.setColor(new Color(mCurrentColor));

        mPath = new Path();
        mDstPath = new Path();
        mPathMeasure = new PathMeasure(mPath, false);

        mDuration = DEFAULT_DURATION;
        mViewTranslationX = viewTranslationX;
        if (isSelected) {
            mFraction = 1;
            mCurrentState = STATE_SELECT;
        } else {
            mFraction = 0;
            mCurrentState = STATE_UNSELECT;
        }
        addDrawTask(this);
        setLayoutRefreshedListener(this);
    }

    @Override
    public void onRefreshed(Component component) {
        int h = component.getHeight();
        int w = component.getWidth();
        mHeight = h * 4 / 5;
        mWidth = h * 2.5f;  //控件长宽比定义为 5 : 2
        mCenterX = w / 2;
        mCenterY = h / 2;
        mCircleRadius = mHeight / 2;
        mRectF = new RectFloat(mCenterX - mCircleRadius * 2, mCenterY - mCircleRadius,
                mCenterX + mCircleRadius * 2, mCenterY + mCircleRadius);   //外圆矩形长宽比定义为 2 : 1
        mPath.addRoundRect(mRectF, mCircleRadius, mCircleRadius, Path.Direction.CLOCK_WISE);
        mPathMeasure.setPath(mPath, false);
        mPathLength = mPathMeasure.getLength();
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        if (!isInit) {
            isInit = true;
            onRefreshed(component);
        }
        canvas.save();
        canvas.translate(mFraction * mViewTranslationX, 0);
        canvas.drawRoundRect(mRectF, mCircleRadius, mCircleRadius, mBgPaint);   //嗷~ 在这画背景线
        mDstPath.reset();
        mPathMeasure.getSegment(0, mPathLength / 2 * mFraction, mDstPath, true);
        canvas.drawPath(mDstPath, mPaint);  //嗷~ 在这画上半圈
        mDstPath.reset();
        mPathMeasure.getSegment(mPathLength - mPathLength / 2 * mFraction, mPathLength, mDstPath, true);
        canvas.drawPath(mDstPath, mPaint);  //嗷~ 在这画下半圈
        mColorPaint.setColor(new Color(mCurrentColor));
        if (mFraction <= 0.8 && mFraction > 0.2) {  //嗷~ 在这画球
            canvas.drawCircle(mCenterX - mCircleRadius + 2 * mCircleRadius * mFraction, mCenterY, mCircleRadius / 6 / 0.6f * (mFraction - 0.2f), mColorPaint);
        } else if (mFraction > 0.8) {
            canvas.drawCircle(mCenterX - mCircleRadius + 2 * mCircleRadius * mFraction, mCenterY, mCircleRadius / 6, mColorPaint);
        }
        canvas.restore();
    }


    public void select() {
        if (mCurrentState == STATE_SELECT) {
            return;
        }
        mCurrentState = STATE_SELECT;
        int start = mBgLineColor;
        int end = mLineColor;
        AnimatorValue animatorValue = new AnimatorValue();
        animatorValue.setCurveType(Animator.CurveType.ACCELERATE_DECELERATE);
        animatorValue.setValueUpdateListener((animatorValue1, v) -> {
            mFraction = v;
            mCurrentColor = getAnimateColor(start, end, v).asArgbInt();
            invalidate();
        });
        animatorValue.start();
    }

    public void unSelect() {
        if (mCurrentState == STATE_UNSELECT) {
            return;
        }
        mCurrentState = STATE_UNSELECT;
        AnimatorValue animatorValue = new AnimatorValue();
        int start = mLineColor;
        int end = mBgLineColor;
        animatorValue.setDuration(mDuration);
        animatorValue.setCurveType(Animator.CurveType.ACCELERATE_DECELERATE);
        animatorValue.setValueUpdateListener((animatorValue1, v) -> {
            mFraction = 1 - v;
            mCurrentColor = getAnimateColor(start, end, v).asArgbInt();
            invalidate();
        });
        animatorValue.start();
    }

    public boolean isSelected() {
        return mCurrentState == 0;
    }

    public void setDuration(int duration) {
        mDuration = duration;
    }

    private RgbColor getAnimateColor(int from, int to, float value) {
        RgbColor colorFrom = RgbColor.fromArgbInt(from);
        RgbColor colorTo = RgbColor.fromArgbInt(to);
        int red = (int) (colorFrom.getRed() + (colorTo.getRed() - colorFrom.getRed()) * value);
        int blue = (int) (colorFrom.getBlue() + (colorTo.getBlue() - colorFrom.getBlue()) * value);
        int green = (int) (colorFrom.getGreen() + (colorTo.getGreen() - colorFrom.getGreen()) * value);
        int alpha = (int) (colorFrom.getAlpha() + (colorTo.getAlpha() - colorFrom.getAlpha()) * value);
        RgbColor mCurrentColorRgb = new RgbColor(red, green, blue, alpha);
        return mCurrentColorRgb;
    }
}
